#include "scanwidget.h"
#include "csingleteon.h"
#include "antivirus/antiviruswork.h"
#include "invokers/invokerfactory.h"
#include "virusfiledetaildefinition.h"
#include "devcommon.h"
#include "widgets/ddialog.h"

//#include <DFontSizeManager>
//#include <DApplicationHelper>
#include <QListView>
//#include <DSuggestButton>
#include <QDialog>

#include <QHeaderView>
#include <QDebug>
#include <QMenu>
#include <QHeaderView>
#include <QDir>
#include <QGraphicsOpacityEffect>
#include <QThread>


#define TABLE_SPACE 5 // 表栏两边间距
#define TITLE_ICON_WIDTH 96 // 左上角图标的款
#define TITLE_ICON_HEIGHT 96 // 左上角扫描类型图标 高度
#define TABLEVIEW_ROW_HEIGHT 54 // tableview 每列高度
#define BUTTOM_PB_WIDTH 120 // 下布局按钮宽度
#define BUTTOM_PB_HEIGHT 36 // 下布局按钮高度
#define OPERATION_ICON_WIDTH 20 // 信任  隔离 修复 图标 宽度
#define OPERATION_ICON_HEIGHT 20 // 信任修复隔离 图标高度
#define ACTION_ICON_WIDTH 12 // 处理方式图标 宽度
#define ACTION_ICON_HEIGHT 12 // 处理方式图标 高度

#define TABLE_COL_RISKS 0 // table表 第二列 风险项
#define TABLE_COL_STATUS 1 // table表 第三列 状态   处理方式
#define TABLE_COL_OPEARTION 2 // table表 处理方式

#define TABLE_COL_CHECK_STATUS 3 // table表 第七列 选择状态
#define TABLE_COL_INFO_PATH 4 // table表 第八列 回馈信息路径
#define TABLE_COL_INFO_DETAIL 5 // table表 第九列 回馈信息详情
#define TABLE_COL_ACTION_STATUS 6 // table表 第十列 处理状态
#define TABLE_COL_OPERATION_FLAG 7 // table表 第十一列 操作状态
#define TABLE_COL_OPERATION_TYPE 8 // table表 第十二列 操作类型
#define TABLE_COL_OPERATING 9 // TABLE   当前行是否在操作中

#define TABLE_COL_1_WIDTH 420 // table表 第二列 宽度
#define TABLE_COL_2_WIDTH 110 // table表 第三列 宽度
#define TABLE_COL_3_WIDTH 135 // table表 第四列 宽度

#define MAIN_LEFT_MARGINS 30 // 主左边距
#define MAIN_TOP_MARGINS 0 // 主上边距
#define MAIN_RIGHT_MARGINS 30 // 主右边距离
#define MAIN_BUTTOM_MARGINS 10 // 主下边距离
#define TOP_LEFT_MARGINS 0 // 标题左边距
#define TOP_TOP_MARGINS 15 // 标题上边距
#define TOP_RIGHT_MARGINS 0 // 标题右边距离
#define TOP_BUTTOM_MARGINS 0 // 标题下边距离
#define SPACING 5 // 布局间隙

#define PAGE_EMPTY 0 // 没有异常  中间展现无异常图片
#define PAGE_TABLE 1 // 有异常  中间展现表格

#define DIALOG_WIDTH 380 //dialog  宽度
#define DIALOG_HEIGHT 145 //dialog  高度
#define DIALOG_PB_WIDTH 140 //dialog  按钮宽度
#define DIALOG_PB_HEIGHT 36 //dialog  按钮高度

#define SET_ACC_NAME(control, name) SET_ACCESS_NAME(control, scanWidget, name)

ScanWidget::ScanWidget(AntiVirusWork *work, QWidget *parent)
    : QWidget(parent)
    , m_antiViruswork(work)
    , m_monitorInterFaceServer(nullptr)
    , m_pbFinish(nullptr)
    , m_pbRescan(nullptr)
    , m_pbType(nullptr)
    , m_titleLabel(nullptr)
    , m_scanPath(nullptr)
    , m_Santime(nullptr)
    , m_errNum(nullptr)
    , m_iconType(nullptr)
    , m_scanNum(nullptr)
    , m_tableView(nullptr)
    , m_progressBar(nullptr)
    , m_t1(nullptr)
    , m_combobox(nullptr)
    , m_exec(nullptr)
    , m_checkAll(nullptr)
    , m_model(nullptr)
    , m_stackwidget(nullptr)
    , m_pbDone(nullptr)
    , m_totalError(0)
    , m_totalScan(0)
    , m_operationCount(0)
    , m_flagPause(true)
    , m_AhprotectorStopFlag(false)
    , m_progSettingTimer(nullptr)
    , m_scanningProg(0)
    , m_isInScanningUI(false)
    , virusDelegate(new OperationDelegate(this))
{
    // 安全中心 联网管控dbus服务
    m_monitorInterFaceServer = InvokerFactory::GetInstance().CreateInvoker("com.deepin.defender.MonitorNetFlow",
                                                                           "/com/deepin/defender/MonitorNetFlow",
                                                                           "com.deepin.defender.MonitorNetFlow",
                                                                           ConnectType::SYSTEM, this);

    setAccessibleName("ScanWidget");
    setObjectName("ScanWidget");
    installEventFilter(this);
    m_progressBar = new QProgressBar(this);
    SET_ACC_NAME(m_progressBar, progressBar);
    m_checkAll = new QCheckBox(this);
    SET_ACC_NAME(m_checkAll, checkAll);
    initGUI();

    // 进度设置定时器
    m_progSettingTimer = new QTimer(this);
    m_progSettingTimer->setInterval(100);
    connect(m_progSettingTimer, SIGNAL(timeout()), this, SLOT(onProgSettingTimer()));

    m_stackwidget->setCurrentIndex(PAGE_TABLE);
    m_checkAll->setCheckState(Qt::CheckState::Unchecked);
    /***********按钮的信号链接***********/
    //暂停 继续 按钮点击
    connect(m_pbType, SIGNAL(clicked()), this, SLOT(doTypeButtonClick()));
    // 完成按钮
    connect(m_pbDone, SIGNAL(clicked()), this, SLOT(doneButtonClick()));
    // 结束  重新扫描
    connect(m_pbFinish, SIGNAL(clicked()), this, SLOT(doScanFinishClick()));
    connect(m_pbRescan, SIGNAL(clicked()), this, SLOT(doReScan()));
    //全选
    connect(m_checkAll, SIGNAL(stateChanged(int)), this, SLOT(doCheckAllClick(int)));
    // 执行按钮
    connect(m_exec, SIGNAL(clicked()), this, SLOT(execButtonClick()));
    //点击表头的列
    connect(m_tableView->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(sortByTableHeaderClicked(int)));

    // 全选和重新扫描失去焦点
    m_checkAll->setFocusPolicy(Qt::NoFocus);
    m_pbRescan->setFocusPolicy(Qt::NoFocus);

    /********  work *************/
    // dubs扫瞄信号反馈数据
    connect(m_antiViruswork, SIGNAL(sendDissectionResult(QString, double, int, QString)), this, SLOT(doDissectionResult(QString, double, int, QString)));
    // dbus 扫描完成信号
    connect(m_antiViruswork, SIGNAL(sendResultWhileScanFinished(QStringList)), this, SLOT(doScanFinsh(QStringList)));
    //dbus 修复信号
    connect(m_antiViruswork, SIGNAL(sendRepairProblemFileResult(QString)), this, SLOT(doRepairResult(QString)));
    //dbus 信任文件信号
    connect(m_antiViruswork, SIGNAL(sendChangeTrustFilesResult(QString)), this, SLOT(doTruestResult(QString)));
    //dbus 隔离文件信号
    connect(m_antiViruswork, SIGNAL(sendChangeIsolationFilesResult(QString)), this, SLOT(doIsolationResult(QString)));
    //单选点击信号
    connect(virusDelegate, SIGNAL(sendCheckClickSingal()), this, SLOT(doSingalCheckClick()));
    connect(virusDelegate, SIGNAL(suggestStatusChanged(int, int)), this, SLOT(changeSuggestStatus(int, int)));
    connect(virusDelegate, SIGNAL(singleRowOperation(QString, Itemtype)), this, SLOT(singlRowOperation(QString, Itemtype)));
    connect(virusDelegate, SIGNAL(openPresistenEditor(const QModelIndex &)), this, SLOT(slotPresistenEditor(const QModelIndex &)));
}

ScanWidget::~ScanWidget()
{
    // 删除定时器指针
    if (nullptr != m_t1) {
        delete m_t1;
    }

    m_model->clear();
    m_model->deleteLater();
    m_model = nullptr;
}

//设置左上角的图标
void ScanWidget::setIconType(int nType)
{
    if (nType == 0) {
        m_iconType->setPixmap(QIcon::fromTheme("dcc_antiav_all1").pixmap(QSize(TITLE_ICON_WIDTH, TITLE_ICON_HEIGHT)));
    } else if (nType == 1) {
        m_iconType->setPixmap(QIcon::fromTheme("dcc_antiav_quick1").pixmap(QSize(TITLE_ICON_WIDTH, TITLE_ICON_HEIGHT)));
    } else if (nType == 2) {
        m_iconType->setPixmap(QIcon::fromTheme("dcc_antiav_customer1").pixmap(QSize(TITLE_ICON_WIDTH, TITLE_ICON_HEIGHT)));
    }
}

//设置类型  从而改变左上角图标和标题
void ScanWidget::setType(int nType, QString sPath, QString sVersion)
{
    m_antiViruswork->setCurrentScanStatus(ScanStatus::Scanning);
    switch (nType) {
    case 0:
        m_currentType = 0;
        //全盘扫描中
        m_titleLabel->setText(tr("Full scanning"));
        m_titleLabel->setToolTip(m_titleLabel->text());
        m_currentScanType = tr("Full Scan");
        break;
    case 1:
        m_currentType = 1;
        //快速扫描中
        m_titleLabel->setText(tr("Quick scanning"));
        m_titleLabel->setToolTip(m_titleLabel->text());
        m_currentScanType = tr("Quick Scan");
        break;
    case 2:
        //自定义扫描中
        m_currentType = 2;
        m_titleLabel->setText(tr("Custom scanning"));
        m_titleLabel->setToolTip(m_titleLabel->text());
        m_currentScanType = tr("Custom Scan");
        break;
    }
    //展现第一个页面
    m_stackwidget->setCurrentIndex(PAGE_TABLE);

    m_currentScanName = m_titleLabel->text();
    m_scanPathInfo = sPath;
    //总行数
    int count = m_model->rowCount();
    for (int i = count; i >= 0; i--) {
        //清空上次扫描的数据
        m_model->removeRow(i);
    }
    //病毒库版本
    m_currentVersion = sVersion;

    // 扫描前准备
    preScan();

    QString time1 = "00:00:00";
    m_Santime->setText(tr("Time elapsed %1").arg(time1));

    m_checkAll->setDisabled(true);
}

// 扫描前准备
void ScanWidget::preScan()
{
    // 修复的下拉框隐藏 不可以用 内容是修复
    m_combobox->hide();
    m_exec->hide();
    m_combobox->setDisabled(false);
    m_exec->setDisabled(false);
    m_combobox->setCurrentIndex(0);

    //暂停  继续按钮  展现
    m_pbType->show();
    // 为了每次点击进去都是 停止和暂停
    m_pbRescan->hide();
    m_pbFinish->show();

    m_flagPause = true;
    m_pbType->setText(tr("Pause", "button"));
    // 完成按钮隐藏
    m_pbDone->hide();

    //扫描总数
    m_totalScan = 0;
    //异常总数
    m_totalError = 0;
    m_countTime = 0;
    //扫描路径清空
    m_scanPath->setText("");
    setScanNum(m_totalScan);
    setScanErrorNum(m_totalError);
    //开始扫描计时
    startTimer();
    //设置左上角图标
    setIconType(m_currentType);
    //精度条清空
    m_progressBar->setValue(0);
    m_progressBar->show();

    // 处于正在扫描界面
    m_isInScanningUI = true;

    // 创建日志的头文件标题 https://pms.uniontech.com/zentao/bug-view-37299.html
    createLogTitle();
    writeScanDatalog();

    // 开始进度设置定时器
    m_progSettingTimer->start();
    // 重置扫描进度
    m_scanningProg = 0;
}

//设置扫描路径
void ScanWidget::setScanPath(QString sPath)
{
    // 设置扫描路径  如果长了中间省略
    QFontMetrics fontWidth(m_scanPath->font());
    QString elideNote = fontWidth.elidedText(sPath, Qt::ElideMiddle, 550);
    // 最大宽度显示的文字
    m_scanPath->setText(QString("%1").arg(elideNote));
    m_scanPath->setToolTip(QString("%1").arg(sPath));
}

//设置扫描异常数据
void ScanWidget::setScanErrorNum(int nVal)
{
    //发现异常
    m_errNum->setText(tr("Threats: %1").arg(QString::number(nVal)));
}

//设置扫描个数
void ScanWidget::setScanNum(int nValue)
{
    //已经扫描项目
    m_scanNum->setText(tr("Scanned: %1").arg(QString::number(nValue)));
}

//设置进度条
void ScanWidget::setProgressValue(double dVal)
{
    double val1 = dVal * 1000000;
    int current = int(val1);
    m_progressBar->setValue(current);
}

//扫描时间定时器
void ScanWidget::startTimer()
{
    m_t1 = new QTimer(this);
    connect(m_t1, SIGNAL(timeout()), this, SLOT(updateTime()));
    m_t1->start(1000);
}

//下拉框全选修复  隔离  信任的操作
void ScanWidget::allOPeration(Itemtype type)
{
    QStringList list;
    m_combobox->setDisabled(true);
    m_exec->setDisabled(true);
    //本次操作的数据
    m_operationCount = 0;
    //2.得到展现出来所有的路径形象
    //总行数
    m_operationMap.clear();
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        //是否被操作
        bool operaFlag = m_model->data(m_model->index(i, COLUMN_OPERATION), ROLE_OPERATION_FLAG).toBool();
        if (!operaFlag) {
            //没有操作
            bool isChecked = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_CHECKED_STATUS).toBool();
            //如果是选中状态  发送处理信号
            if (isChecked) {
                //文件路径
                QString filePath = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_VIRUSFILE_PATH).toString();
                list.append(filePath);
                m_lastFileName = filePath;
                m_model->setItem(i, TABLE_COL_OPERATING, new QStandardItem(QString("true")));
                m_operationMap.insert(i, true);
                m_model->setData(m_model->index(i, COLUMN_SUGGESTION), true, ROLE_OPERATING_FLAG);
                QModelIndex editorIndex = m_model->index(i, COLUMN_SUGGESTION);
                m_tableView->openPersistentEditor(editorIndex);
            } else {
                m_operationMap.insert(i, false);
            }
        } else {
            m_operationMap.insert(i, true);
        }
        m_model->setData(m_model->index(i, COLUMN_OPERATION), true, ROLE_OPERATION_FLAG);
    }
    int nType = int(type);
    Q_EMIT senBatchOperation(list, nType);

    // 添加安全日志
    if (Itemtype::Repair == Itemtype(nType)) {
        DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Repaired: %1").arg(list.count()));
    } else if (Itemtype::isolation == Itemtype(nType)) {
        DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Quarantined: %1").arg(list.count()));
    } else {
        DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Trusted: %1").arg(list.count()));
    }
}

//设置操作后结果   type 0 修复
void ScanWidget::setOperationResult(QString sPath, Itemtype type)
{
    //总行数
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        //文件路径
        QString filePath = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_VIRUSFILE_PATH).toString();
        if (filePath == sPath) {
            //1. 如果路径相同  给改相应的图标
            m_model->setItem(i, TABLE_COL_OPERATING, new QStandardItem(QString("fasle")));

            //操作后的状态
            QString status;
            //操作类型   0未操作  1 修复  2 隔离  3信任
            QString actionType;
            switch (type) {
            case Itemtype::Repair:
                status = QString(tr("Repaired"));
                changeSuggestStatus(i, 1);
                actionType = "1";
                break;
            case Itemtype::Delete:
                break;
            case Itemtype::isolation:
                actionType = "2";
                changeSuggestStatus(i, 2);
                status = QString(tr("Quarantined"));
                break;
            case Itemtype::Trust:
                actionType = "3";
                changeSuggestStatus(i, 3);
                status = QString(tr("Trusted"));
                break;
            }
            //2.设置修改后的内容 内容伴随宽度省略 和提示信息显显示
            //操作状态
            m_model->setItem(i, TABLE_COL_ACTION_STATUS, new QStandardItem(QString("%1").arg(status)));
            //设置该行已经操作
            m_model->setItem(i, TABLE_COL_OPERATION_FLAG, new QStandardItem(QString("true")));
            m_model->setData(m_model->index(i, COLUMN_OPERATION), true, ROLE_OPERATION_FLAG);
            m_model->setData(m_model->index(i, COLUMN_SUGGESTION), false, ROLE_OPERATING_FLAG);
            QModelIndex editorIndex = m_model->index(i, COLUMN_SUGGESTION);
            m_tableView->closePersistentEditor(editorIndex);
            //操作类型
            m_model->setItem(i, TABLE_COL_OPERATION_TYPE, new QStandardItem(QString("%1").arg(actionType)));
            m_tableView->setColumnHidden(TABLE_COL_ACTION_STATUS, true);
            m_tableView->setColumnHidden(TABLE_COL_OPERATION_FLAG, true);
            m_tableView->setColumnHidden(TABLE_COL_OPERATION_TYPE, true);
            m_tableView->setColumnHidden(TABLE_COL_OPERATING, true);

            //操作的项数增加
            ++m_operationCount;
        }
        //判断是不是在处理最后一个
        if (m_lastFileName == sPath) {
            //处理结束
            m_titleLabel->setText(tr("The threats are processed successfully"));
            m_titleLabel->setToolTip(m_titleLabel->text());
            // 获得操作的数据明细
            QList<int> list;
            list = getOperationinfo();

            // 信任文件 隔离文件  信任文件
            m_scanPath->setText(tr("Repaired: %1   Quarantined: %2   Trusted: %3").arg(list.at(1)).arg(list.at(2)).arg(list.at(3)));
            QString procsssInfo = m_scanPath->text();
            m_scanPath->setToolTip(procsssInfo);
            m_Santime->setText(" ");

            // 处理完本次最后一个文件 判断可以操作的按钮状态  true 可以操作  false不可以操作
            bool flag = checkOperationBtStatus();
            if (flag) {
                // 下拉框可以操作
                m_combobox->setDisabled(false);
                m_exec->setDisabled(false);
            } else {
                // 下拉框不可以操作
                m_combobox->setDisabled(true);
                m_exec->setDisabled(true);
            }

            // 设置是处理中的状态
            m_antiViruswork->setThreatsOperationStatus(false);
            // 更新返回按钮
            m_antiViruswork->updateBackButton();

            //如果操作总数等于列表总数  即所有的都完成
            bool finishFlag;
            finishFlag = finishAllOperation();
            if (finishFlag == true) {
                //如果都操作了
                m_combobox->hide();
                m_exec->hide();

                // 状态按钮隐藏  完成按钮展现
                m_pbType->hide();
                m_pbDone->show();
                // 异常都操作了以后 对异常数据在数据库中的操作mxz https://pms.uniontech.com/zentao/bug-view-41197.html
                addThreats();

                // 异常结果处理完成后，则直接设置引擎状态为free，将引擎扫描功能供给其他模块使用
                m_antiViruswork->setCurrentScanStatus(ScanStatus::Free);
            }
            //写入扫描数据log
            writeScanDatalog();

            for (int resultIndex = 0; resultIndex < m_operationMap.count(); resultIndex++) {
                m_model->setData(m_model->index(resultIndex, COLUMN_OPERATION), m_operationMap.value(resultIndex), ROLE_OPERATION_FLAG);
            }
        }
    }
}

//写扫描日志数据
void ScanWidget::writeScanDatalog()
{
    QList<int> list;
    //获得操作的数据明细
    list = getOperationinfo();
    QDateTime date = QDateTime::currentDateTime();
    QFile f(m_logName);
    if (!f.open(QIODevice::ReadOnly | QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Open ScanDate.log failed." << endl;
        return;
    }
    //输出流
    QTextStream outstream(&f);
    QString info = QString(tr("【Scan Information】"));
    outstream << info << "\n";
    QString version = QString(tr("Virus Database:"));
    //版本
    outstream << version << m_currentVersion << "\n";
    //  扫描时间：
    QString scanTime = QString(tr("Scan Time:"));
    QString updateTime = date.toString("yyyy-MM-dd hh:mm:ss");
    outstream << scanTime << updateTime << "\n";
    //扫描类型：
    QString scanType = QString(tr("Scan Type:"));
    outstream << scanType << m_currentScanType << "\n";
    //扫描范围：
    QString scanScope = QString(tr("Scan Scope:"));
    outstream << scanScope << m_scanPathInfo << "\n";
    outstream << "\n";
    //【扫描结果】
    QString scanResult = QString(tr("【Scan Result】"));
    outstream << scanResult << "\n";
    //扫描文件数：
    QString scanFiles = QString(tr("Files Scanned:"));
    outstream << scanFiles << m_totalScan << "\n";
    //发现风险数：
    QString scanError = QString(tr("Threats Found:"));
    outstream << scanError << m_totalError << "\n";
    //已经操作风险数：
    QString scanDisposeError = QString(tr("Threats Resolved:"));
    outstream << scanDisposeError << m_totalError - list.at(0) << "\n";
    //已经修复数：
    QString repairError = QString(tr("Repaired:"));
    outstream << repairError << list.at(1) << "\n";
    //已经隔离数：
    QString isolationError = QString(tr("Quarantined:"));
    outstream << isolationError << list.at(2) << "\n";
    //已经信任数：
    QString trustError = QString(tr("Trusted:"));
    outstream << trustError << list.at(3) << "\n";
    //类型标识 0 全盘扫描 1 快速程序  2 自定义扫描
    outstream << "Type_Flag>>" << m_currentType << "\n";

    outstream << "\n";
    //【扫描详情】
    QString scanDetails = QString(tr("【Scan Details】"));
    outstream << scanDetails << "\n";
    outstream << "==========================="
              << "\n";
    int datelenth = m_model->rowCount(); //总行数
    for (int i = 0; i < datelenth; i++) {
        //文件路径
        QString filePath = m_model->index(i, TABLE_COL_INFO_PATH).data(Qt::DisplayRole).toString();
        //文件类型
        QString message = m_model->index(i, TABLE_COL_INFO_DETAIL).data(Qt::DisplayRole).toString();
        //处理的结果
        QString workstatus = m_model->index(i, TABLE_COL_ACTION_STATUS).data(Qt::DisplayRole).toString();
        if (workstatus == "建议修复" || workstatus == "To be repaired") {
            //未处理
            workstatus = QString(tr("Unsolved"));
        }
        outstream << filePath << "\n";
        outstream << message << "[" << workstatus << "]"
                  << "\n";
    }
    f.close();
}

//更改全选状态
void ScanWidget::updateCheckAllStaus()
{
    //总行数
    int count = m_model->rowCount();
    //选中状态的map
    QMap<int, int> rowMap;
    for (int i = 0; i < count; i++) {
        bool isChecked = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_CHECKED_STATUS).toBool();
        if (isChecked) {
            rowMap.insert(i, 1);
            //            m_model->item(i, TABLE_COL_CHECK_STATUS)->setText("1");
        } else {
            rowMap.insert(i, 0);
            //            m_model->item(i, TABLE_COL_CHECK_STATUS)->setText("0");
        }
    }
    //打沟的数量
    int tcount = 0;
    //不打沟的数量
    int fcount = 0;
    //便利状态map
    QMapIterator<int, int> rowMapIterator(rowMap);
    rowMapIterator.toBack();
    while (rowMapIterator.hasPrevious()) {
        int value;
        rowMapIterator.previous();
        value = rowMapIterator.value();
        if (value == 0) {
            fcount++;
        } else if (value == 1) {
            tcount++;
        }
    }
    //根据数量判断  全选状态
    if (tcount == count) {
        m_checkAll->setCheckState(Qt::CheckState::Checked);
        // 全选 下拉框可以操作
        m_combobox->setDisabled(false);
        m_exec->setDisabled(false);
    } else if (fcount == count) {
        m_checkAll->setCheckState(Qt::CheckState::Unchecked);
        // 下拉框不可以操作
        m_combobox->setDisabled(true);
        m_exec->setDisabled(true);
    } else {
        //有一个没有选中  先把全选设为未选择状态   然后把以前的选中都恢复
        m_checkAll->setCheckState(Qt::CheckState::Unchecked);
        QMap<int, int>::iterator it;
        for (it = rowMap.begin(); it != rowMap.end(); ++it) {
            int row = it.key();
            if (0 == it.value()) {
                m_model->setData(m_model->index(row, COLUMN_RISKS), false, ROLE_CHECKED_STATUS);
            } else {
                m_model->setData(m_model->index(row, COLUMN_RISKS), true, ROLE_CHECKED_STATUS);
            }
        }
    }

    // 判断可以操作的按钮状态  true 可以操作  false不可以操作
    bool flag = checkOperationBtStatus();
    if (flag) {
        // 下拉框可以操作
        m_combobox->setDisabled(false);
        m_exec->setDisabled(false);
    } else {
        // 下拉框不可以操作
        m_combobox->setDisabled(true);
        m_exec->setDisabled(true);
    }
}

//添加数据
void ScanWidget::appendFileInfo(QString sPath, QString detail)
{
    //锁
    DEFENDER_MUTEX_LOCKER(&SMutex::getInstance().m_mutex);
    int row = m_model->rowCount();
    QStandardItem *c0 = new QStandardItem();
    QStandardItem *c1 = new QStandardItem();
    QStandardItem *c2 = new QStandardItem();

    m_model->setItem(row, 0, c0);
    m_model->setItem(row, 1, c1);
    m_model->setItem(row, 2, c2);
    c0->setData(true, ROLE_CHECKED_STATUS);
    c0->setData(sPath, ROLE_VIRUSFILE_PATH);
    c0->setData(detail, ROLE_VIRUSFILE_NAME);
    c1->setData(0, ROLE_SUGGESTION_STATUS);
    c2->setData(true, ROLE_OPERATION_FLAG);
    c2->setData(false, ROLE_OPERATING_FLAG);

    m_model->setItem(row, TABLE_COL_INFO_PATH, new QStandardItem(QString("%1").arg(sPath)));
    m_model->setItem(row, TABLE_COL_OPERATION_TYPE, new QStandardItem(QString("0")));
}

void ScanWidget::refreshElideText()
{
    QFontMetrics fontmet(m_pbFinish->font());
    QString removeText = tr("Finish", "button");
    QString elidedStr = fontmet.elidedText(removeText, Qt::TextElideMode::ElideMiddle, BUTTOM_PB_WIDTH - 10);
    m_pbFinish->setText(elidedStr);
    if (fontmet.width(removeText) > BUTTOM_PB_WIDTH - 10) {
        m_pbFinish->setToolTip(removeText);
    } else {
        m_pbFinish->setToolTip("");
    }

    removeText = tr("Scan Again");
    elidedStr = fontmet.elidedText(removeText, Qt::TextElideMode::ElideMiddle, BUTTOM_PB_WIDTH - 14);
    m_pbRescan->setText(elidedStr);
    if (fontmet.width(removeText) > BUTTOM_PB_WIDTH - 14) {
        m_pbRescan->setToolTip(removeText);
    } else {
        m_pbRescan->setToolTip("");
    }

    removeText = tr("Pause");
    elidedStr = fontmet.elidedText(removeText, Qt::TextElideMode::ElideMiddle, BUTTOM_PB_WIDTH - 10);
    m_pbType->setText(elidedStr);
    if (fontmet.width(removeText) > BUTTOM_PB_WIDTH - 10) {
        m_pbType->setToolTip(removeText);
    } else {
        m_pbType->setToolTip("");
    }
}

void ScanWidget::changeSuggestStatus(int row, int status)
{
    m_model->setData(m_model->index(row, COLUMN_SUGGESTION), status, ROLE_SUGGESTION_STATUS);
}

void ScanWidget::slotPresistenEditor(const QModelIndex &index)
{
    m_tableView->openPersistentEditor(index);
}

void ScanWidget::onProgSettingTimer()
{
    setScanPath(m_scanningFilePath);
    setProgressValue(m_scanningProg);
}

//是否结束全部操作
bool ScanWidget::finishAllOperation()
{
    bool flag;
    //行数
    int count = m_model->rowCount();
    int actionNum = 0;
    //只有是所有的第10项目为 true 才是结束
    for (int i = 0; i < count; i++) {
        QString operaFlag = m_model->index(i, TABLE_COL_OPERATION_FLAG).data(Qt::DisplayRole).toString();
        if (operaFlag == "true") {
            ++actionNum;
        }
    }
    if (actionNum == count) {
        flag = true;
        addThreats();
    } else {
        flag = false;
    }
    return flag;
}

//获得操作的信息
QList<int> ScanWidget::getOperationinfo()
{
    QList<int> list;
    //行数
    int count = m_model->rowCount();
    //已修复
    int repaired = 0;
    //没有操作
    int noAction = 0;
    //已隔离
    int isolationed = 0;
    //已信任
    int trusted = 0;
    //只有是所有的第10项目为 true 才是结束
    for (int i = 0; i < count; i++) {
        //操作状态
        QString actionType = m_model->index(i, TABLE_COL_OPERATION_TYPE).data(Qt::DisplayRole).toString();
        if (actionType == "0") {
            ++noAction;
        } else if (actionType == "1") {
            ++repaired;
        } else if (actionType == "2") {
            ++isolationed;
        } else {
            ++trusted;
        }
    }
    list << noAction << repaired << isolationed << trusted;
    return list;
}

void ScanWidget::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
}

bool ScanWidget::eventFilter(QObject *obj, QEvent *event)
{
    if (this == obj) {
        // 如果当前是字体改变的事件
        if (event->type() == QEvent::FontChange) {
            // 更新按钮文本
            refreshElideText();
        }
    }
    return QWidget::eventFilter(obj, event);
}

//布局
void ScanWidget::initGUI()
{
    //主垂直布局
    QVBoxLayout *mainlayout = new QVBoxLayout;
    mainlayout->setSpacing(SPACING);
    //四周边距
    mainlayout->setContentsMargins(MAIN_LEFT_MARGINS, MAIN_TOP_MARGINS, MAIN_RIGHT_MARGINS, MAIN_BUTTOM_MARGINS);

    //图表和右侧扫描标题布局
    QHBoxLayout *hLayout2 = new QHBoxLayout();
    //头部右侧垂直布局
    QVBoxLayout *vlayout1 = new QVBoxLayout;
    vlayout1->setSpacing(0);
    vlayout1->setContentsMargins(TOP_LEFT_MARGINS, TOP_TOP_MARGINS, TOP_RIGHT_MARGINS, TOP_BUTTOM_MARGINS);
    //上布局
    QVBoxLayout *vlayout2 = new QVBoxLayout;
    vlayout2->setSpacing(SPACING);
    QHBoxLayout *thlayout = new QHBoxLayout;
    //标题
    m_titleLabel = new QLabel(tr("Full scanning..."), this);
    SET_ACC_NAME(m_titleLabel, titleLable);
    m_titleLabel->setToolTip(m_titleLabel->text());
//    m_titleLabel->setElideMode(Qt::TextElideMode::ElideMiddle);
    QFont ft = m_titleLabel->font();
    ft.setBold(true);
    m_titleLabel->setFont(ft);
//    DFontSizeManager::instance()->bind(m_titleLabel, DFontSizeManager::T4);
    thlayout->addWidget(m_titleLabel, 0, Qt::AlignLeft);
    //扫描时间
    QString time1 = "00:00:00";
    m_Santime = new QLabel(tr("Time elapsed %1").arg(time1), this);
    SET_ACC_NAME(m_Santime, scanTimeLable);
    m_Santime->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    QFont ft2 = m_Santime->font();
    ft2.setBold(false);
    m_Santime->setFont(ft2);
//    DFontSizeManager::instance()->bind(m_Santime, DFontSizeManager::T7);
    thlayout->addWidget(m_Santime, 0, Qt::AlignRight);
    vlayout1->addLayout(thlayout, 0);

    //进度条
    m_progressBar->setObjectName(QString("progressBar"));
    m_progressBar->setMinimumSize(QSize(0, 8));
    m_progressBar->setMaximumSize(QSize(16777215, 8));
    m_progressBar->setRange(0, 1000000);
    //默认值
    m_progressBar->setValue(0);
    m_progressBar->setTextVisible(false);
    vlayout1->addWidget(m_progressBar);
    //扫描路径
    m_scanPath = new QLabel("Scan path...", this);
    SET_ACC_NAME(m_scanPath, scanPathLable);
    QFont ft1 = m_scanPath->font();
    ft1.setBold(false);
    m_scanPath->setFont(ft1);
//    DFontSizeManager::instance()->bind(m_scanPath, DFontSizeManager::T7);
    vlayout1->addWidget(m_scanPath);

    m_iconType = new QLabel(this);
    SET_ACC_NAME(m_iconType, iconTypeLable);
    m_iconType->setMinimumSize(QSize(TITLE_ICON_WIDTH + 14, TITLE_ICON_HEIGHT + 14));
    m_iconType->setMaximumSize(QSize(TITLE_ICON_WIDTH + 14, TITLE_ICON_HEIGHT + 14));
    //左侧的图表
    hLayout2->addWidget(m_iconType);
    hLayout2->addLayout(vlayout1);
    vlayout2->addLayout(hLayout2);
    //空格
    mainlayout->addSpacing(5);

    //空格
    mainlayout->addSpacing(SPACING);
    mainlayout->addLayout(vlayout2);

    // 栈 stacke
    m_stackwidget = new QStackedWidget(this);
    SET_ACC_NAME(m_stackwidget, stackWidget);
    m_stackwidget->setContentsMargins(0, 0, 0, 0);

    // 栈 第一页
    QWidget *widget1 = new QWidget(this);
    SET_ACC_NAME(widget1, widget1);
    QHBoxLayout *tlayout = new QHBoxLayout;
    QLabel *m_empty = new QLabel(this);
    SET_ACC_NAME(m_empty, emptyLable);
    m_empty->setPixmap(QIcon(":/icons/deepin/builtin/icons/dcc_antiav_empty_100px.svg").pixmap(QSize(100, 84)));
    tlayout->addWidget(m_empty, 0, Qt::AlignVCenter | Qt::AlignHCenter);
    widget1->setLayout(tlayout);
    m_stackwidget->addWidget(widget1);

    // 栈 第二页 tableview
    QWidget *CenterWidget = new QWidget(this);
    SET_ACC_NAME(CenterWidget, centerWidget);
    CenterWidget->setLayout(initTableWidget());
    m_stackwidget->addWidget(CenterWidget);
    mainlayout->addWidget(m_stackwidget, Qt::AlignBottom | Qt::AlignHCenter);

    //下布局
    QVBoxLayout *vlayout3 = new QVBoxLayout;

    //扫描的项目   报警  和个数
    QHBoxLayout *hLayout3 = new QHBoxLayout();

    //按钮
    QHBoxLayout *hLayout4 = new QHBoxLayout();

    //下画线
    hLayout3->setContentsMargins(10, -1, 15, -1);
    hLayout3->setSpacing(SPACING);

    //全选
    m_checkAll->setText(tr("Select All"));
    hLayout3->addWidget(m_checkAll, 0, Qt::AlignBottom | Qt::AlignLeft);

    //异常
    m_errNum = new QLabel(tr("Threats:"), this);
    SET_ACC_NAME(m_errNum, threatNumLable);
    m_errNum->setAlignment(Qt::AlignLeft | Qt::AlignTrailing | Qt::AlignVCenter);
//    m_errNum->setElideMode(Qt::TextElideMode::ElideMiddle);
    hLayout3->addWidget(m_errNum, 0, Qt::AlignBottom | Qt::AlignLeft);

    //已经扫描项目
    m_scanNum = new QLabel(tr("Scanned:"), this);
    SET_ACC_NAME(m_scanNum, scannedNumLable);
    m_scanNum->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
//    m_scanNum->setElideMode(Qt::TextElideMode::ElideMiddle);
    hLayout3->addWidget(m_errNum, 0, Qt::AlignBottom | Qt::AlignLeft);
    hLayout3->addStretch(1);
    hLayout3->addWidget(m_scanNum);
    vlayout3->addLayout(hLayout3);

    hLayout4->setSpacing(20);
    hLayout4->setContentsMargins(10, 0, 0, 0);

    // 结束按钮
    m_pbFinish = new QPushButton(this);
    SET_ACC_NAME(m_pbFinish, finishButton);
    m_pbFinish->setText(tr("Finish", "button"));
    m_pbFinish->setMinimumSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    m_pbFinish->setMaximumSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));

    // 重新扫描
    m_pbRescan = new QPushButton(this);
    SET_ACC_NAME(m_pbRescan, rescanButton);
    m_pbRescan->setText(tr("Scan Again"));
    m_pbRescan->setMinimumSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    m_pbRescan->setMaximumSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));

    //暂停按钮
    m_pbType = new QPushButton(this);
    SET_ACC_NAME(m_pbType, stopButton);
    m_pbType->setText(tr("Pause", "button"));
    m_pbType->setMinimumSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    m_pbType->setMaximumSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    hLayout4->addWidget(m_pbFinish, 0, Qt::AlignLeft);
    hLayout4->addWidget(m_pbRescan, 0, Qt::AlignLeft);
    hLayout4->addStretch(1);
    hLayout4->addWidget(m_pbType, 0, Qt::AlignRight);

    // 完成按钮
    m_pbDone = new QPushButton(this);
    SET_ACC_NAME(m_pbDone, doneButton);
    m_pbDone->setText(tr("Done", "button"));
    m_pbDone->setFixedSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    hLayout4->addWidget(m_pbDone, 0, Qt::AlignRight);

    refreshElideText();

    // 下拉按钮 combobox
    m_combobox = new QComboBox(this);
    m_combobox->clear();
    m_combobox->setAccessibleDescription("combox");
    SET_ACC_NAME(m_combobox, comboxDown);
    QStringList comlist;
    comlist << tr("Repair Now") << tr("Quarantine Now") << tr("Add to Whitelist");
    m_combobox->addItems(comlist);
    SET_ACC_NAME(m_combobox->view(), actionList);
    m_combobox->setFixedSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    hLayout4->addWidget(m_combobox, 0, Qt::AlignRight);

    // 执行按钮
    m_exec = new QPushButton(this);
    SET_ACC_NAME(m_exec, execButton);
    m_exec->setText(tr("Start", "button"));
    m_exec->setFixedSize(QSize(BUTTOM_PB_WIDTH, BUTTOM_PB_HEIGHT));
    hLayout4->addWidget(m_exec, 0, Qt::AlignRight);

    vlayout3->addLayout(hLayout4);
    mainlayout->addLayout(vlayout3);

    setLayout(mainlayout);
}

// 初始化表格
QHBoxLayout *ScanWidget::initTableWidget()
{
    QHBoxLayout *layout = new QHBoxLayout;
    layout->setMargin(0);
    layout->setSpacing(0);
    m_tableView = new QTableView(this);
    SET_ACC_NAME(m_tableView, tableView);
    SET_ACC_NAME(m_tableView->viewport(), viewPort);
    m_model = new QStandardItemModel(this);
    //     连接表格与模型
    m_tableView->setItemDelegate(virusDelegate);

    m_tableView->setModel(m_model);
    layout->addWidget(m_tableView);

    //tableview 表高度
    m_tableView->verticalHeader()->setDefaultSectionSize(TABLEVIEW_ROW_HEIGHT);
    m_tableView->verticalHeader()->setVisible(false);
    m_tableView->horizontalHeader()->setVisible(true);
    m_tableView->horizontalHeader()->setStretchLastSection(true);
    //单选
    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_tableView->setSelectionMode(QAbstractItemView::NoSelection);
    //不可以编辑
    m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    //形状
    m_tableView->setFrameShape(QTableView::NoFrame);
    // 失去焦点
    m_tableView->setFocusPolicy(Qt::NoFocus);
    //栅格
    m_tableView->setShowGrid(false);
    //排序
    m_tableView->setSortingEnabled(true);
    m_tableView->setMouseTracking(true);

    //风险项
    QStandardItem *standaritem1 = new QStandardItem(tr("Risks"));
    standaritem1->setAccessibleText("Risk");
    standaritem1->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    //状态   处理方式
    QStandardItem *standaritem2 = new QStandardItem(tr("Status"));
    standaritem2->setAccessibleText("Status");
    standaritem2->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    //处理方式
    QStandardItem *standaritem3 = new QStandardItem(tr("Action"));
    standaritem3->setAccessibleText("Action");
    standaritem3->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    //设置每列
    m_model->setHorizontalHeaderItem(TABLE_COL_RISKS, standaritem1);
    m_model->setHorizontalHeaderItem(TABLE_COL_STATUS, standaritem2);
    m_model->setHorizontalHeaderItem(TABLE_COL_OPEARTION, standaritem3);

    //选择状态
    m_model->setHorizontalHeaderItem(TABLE_COL_CHECK_STATUS, new QStandardItem("checkStatus"));
    //回馈信息路径
    m_model->setHorizontalHeaderItem(TABLE_COL_INFO_PATH, new QStandardItem("InfoPath"));
    //回馈信息内容
    m_model->setHorizontalHeaderItem(TABLE_COL_INFO_DETAIL, new QStandardItem("InfoDetail"));
    //操作状态
    m_model->setHorizontalHeaderItem(TABLE_COL_ACTION_STATUS, new QStandardItem("ActionStatus"));
    //是否操作了   //操作为True   为操作为 false
    m_model->setHorizontalHeaderItem(TABLE_COL_OPERATION_FLAG, new QStandardItem("flag"));
    //操作类型   0没有操作  1修复  2隔离  3信任   由于操作状态保存的是英文或中文判断比较麻烦
    m_model->setHorizontalHeaderItem(TABLE_COL_OPERATION_TYPE, new QStandardItem("type"));
    m_model->setHorizontalHeaderItem(TABLE_COL_OPERATING, new QStandardItem("operation"));
    //设置每列的宽度
    m_tableView->setColumnWidth(TABLE_COL_RISKS, TABLE_COL_1_WIDTH);
    m_tableView->setColumnWidth(TABLE_COL_STATUS, TABLE_COL_2_WIDTH);
    m_tableView->setColumnWidth(TABLE_COL_OPEARTION, TABLE_COL_3_WIDTH);

    //隐藏列
    m_tableView->setColumnHidden(TABLE_COL_CHECK_STATUS, true);
    m_tableView->setColumnHidden(TABLE_COL_INFO_PATH, true);
    m_tableView->setColumnHidden(TABLE_COL_INFO_DETAIL, true);
    m_tableView->setColumnHidden(TABLE_COL_ACTION_STATUS, true);
    m_tableView->setColumnHidden(TABLE_COL_OPERATION_FLAG, true);
    m_tableView->setColumnHidden(TABLE_COL_OPERATION_TYPE, true);
    m_tableView->setColumnHidden(TABLE_COL_OPERATING, true);

    m_tableView->horizontalHeader()->setSortIndicator(TABLE_COL_CHECK_STATUS, Qt::DescendingOrder); //排序
    m_tableView->horizontalHeader()->setSortIndicator(TABLE_COL_INFO_PATH, Qt::DescendingOrder); //排序

    return layout;
}

// 扫描结束按钮点击
void ScanWidget::doScanFinishClick()
{
    m_pbFinish->setEnabled(false);
    m_antiViruswork->setCurrentScanStatus(ScanStatus::Free);
    // 停止扫描
    stopScan();
}

// 重新扫描
void ScanWidget::doReScan()
{
    bool result = isCurrentOperating();
    if (result == true) {
        showOperatingTip();
    } else {
        addThreats();
        m_t1->stop();
        // 停止进度设置定时器
        m_progSettingTimer->stop();
        // 不处于正在扫描界面
        m_isInScanningUI = false;

        // 如果当前处于有异常结果页
        if (ScanStatus::ResultThreats == m_antiViruswork->getCurrentScanStatus()) {
            // 异步设置病毒查杀服务标志位为空闲
            m_antiViruswork->setCurrentScanStatus(ScanStatus::Free);
            // 消息循环等待病毒查杀服务标志位为空闲
            while (ScanStatus::Free != m_antiViruswork->getCurrentScanStatus()) {
                //QThread::currentThread()->msleep(50);
                Devcommon::delay_ms(50);
                qApp->processEvents();
            }
        }

        Q_EMIT scanAgain(m_currentType, m_scanPathInfo, m_currentVersion);
    }
}

// 暂停和继续按钮点击
void ScanWidget::doTypeButtonClick()
{
    m_pbType->setEnabled(false);
//    QTimer::singleShot(1000, this, [=]() {
//        m_pbType->setEnabled(true);
//    });

    if (m_flagPause) {
        //暂停
        m_antiViruswork->setCurrentScanStatus(ScanStatus::Pausing);
        //下个是继续
        m_pbType->setText(tr("Continue", "button"));

        // 缓存定时器停止  https://pms.uniontech.com/zentao/bug-view-37217.html
        // 设置扫描标题已经暂停
        m_t1->stop();
        // 停止进度设置定时器
        m_progSettingTimer->stop();
        // 不处于正在扫描界面
        m_isInScanningUI = false;
        m_titleLabel->setText(tr("%1 paused").arg(m_currentScanType));
        m_titleLabel->setToolTip(m_titleLabel->text());
    } else {
        //继续
        m_antiViruswork->setCurrentScanStatus(ScanStatus::Scanning);
        //下个是暂停
        m_pbType->setText(tr("Pause", "button"));

        // 缓存定时器继续  扫描计时器启动  https://pms.uniontech.com/zentao/bug-view-37217.html
        m_t1->start(1000);
        // 开始进度设置定时器
        m_progSettingTimer->start();
        // 重置扫描进度
        m_scanningProg = 0;
        // 处于正在扫描界面
        m_isInScanningUI = true;
    }
    m_flagPause = !m_flagPause;

    // 暂停或者继续记录数据 https://pms.uniontech.com/zentao/bug-view-37299.html
    writeScanDatalog();

    m_pbType->setEnabled(true);
}

void ScanWidget::updateTime()
{
    m_countTime++;
    int yu = m_countTime % 6;

    QString point = "";
    if (yu == 0) {
        point = ".";
    } else if (yu == 1) {
        point = "..";
    } else if (yu == 2) {
        point = "...";
    } else if (yu == 3) {
        point = "....";
    } else if (yu == 4) {
        point = ".....";
    } else if (yu == 5) {
        point = "......";
    }
    m_titleLabel->setText(QString("%1 %2").arg(m_currentScanName).arg(point));
    m_titleLabel->setToolTip(m_titleLabel->text());
    //小时
    int h = m_countTime / 3600;
    //分钟
    int m = (m_countTime - h * 3600) / 60;
    //秒
    int s = (m_countTime - h * 3600 - m * 60) % 60;
    m_Santime->setText(QString(tr("Time elapsed %1:%2:%3")
                                   .arg(h, 2, 10, QChar('0'))
                                   .arg(m, 2, 10, QChar('0'))
                                   .arg(s, 2, 10, QChar('0'))));
}

//全选
void ScanWidget::doCheckAllClick(int nStatus)
{
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        //　对已经操作了的不会有全选操作　https://pms.uniontech.com/zentao/bug-view-45727.html
        bool operaFlag = m_model->data(m_model->index(i, COLUMN_OPERATION), ROLE_OPERATION_FLAG).toBool();
        if (!operaFlag) {
            //　如果该行没有操作　　执行全选/反全选状态改变
            switch (nStatus) {
            case 0:
                m_model->setData(m_model->index(i, COLUMN_RISKS), false, ROLE_CHECKED_STATUS);

                // 下拉框不可以操作
                m_combobox->setDisabled(true);
                m_exec->setDisabled(true);
                break;
            case 1:
                break;
            case 2:
                m_model->setData(m_model->index(i, COLUMN_RISKS), true, ROLE_CHECKED_STATUS);

                // 全选 下拉框可以操作
                m_combobox->setDisabled(false);
                m_exec->setDisabled(false);
                break;
            }
        }
    }
}

//扫描结束展现出 全选框和修复等下拉框
void ScanWidget::doScanFinsh(QStringList list)
{
    Q_UNUSED(list);
    // 当已经处于结果页，则不重新展示结果
    if (!m_isInScanningUI) {
        return;
    }

    m_t1->stop();
    // 停止进度设置定时器
    m_progSettingTimer->stop();
    // 不处于正在扫描界面
    m_isInScanningUI = false;
    // 结束后的页面
    showFinishPage();
}

//修复回馈信号
void ScanWidget::doRepairResult(QString sPath)
{
    setOperationResult(sPath, Itemtype::Repair);
}

//隔离回馈信号
void ScanWidget::doIsolationResult(QString sPath)
{
    setOperationResult(sPath, Itemtype::isolation);
}

//信任隔离信号
void ScanWidget::doTruestResult(QString sPaths)
{
    setOperationResult(sPaths, Itemtype::Trust);
}

//单选点击
void ScanWidget::doSingalCheckClick()
{
    m_combobox->clearFocus();
    updateCheckAllStaus();
}

// 完成按钮点击
void ScanWidget::doneButtonClick()
{
    // 只有当前扫描状态为 扫描结果页，才可置状态位为空闲
    if (ScanStatus::ResultThreats == m_antiViruswork->getCurrentScanStatus()
        || ScanStatus::ResultNoThreats == m_antiViruswork->getCurrentScanStatus()) {
        m_antiViruswork->setCurrentScanStatus(ScanStatus::Free);
    }

    addThreats();
    Q_EMIT onBackpage();
    // 更新返回按钮
    m_antiViruswork->updateBackButton();
}

// 执行按钮点击
void ScanWidget::execButtonClick()
{
    // 失去焦点
    m_combobox->clearFocus();
    // 设置是处理中的状态
    m_antiViruswork->setThreatsOperationStatus(true);
    // 更新返回按钮
    m_antiViruswork->updateBackButton();
    // 根据当前的combox 下标
    int index = m_combobox->currentIndex();
    // 根据下表触发不同的条件
    if (index == 0) {
        doRepairClick();
    } else if (index == 1) {
        doIsolationClick();
    } else {
        doTrustClick();
    }
}

//全部修复
void ScanWidget::doRepairClick()
{
    allOPeration(Itemtype::Repair);
}

//隔离
void ScanWidget::doIsolationClick()
{
    allOPeration(Itemtype::isolation);
}

//信任
void ScanWidget::doTrustClick()
{
    allOPeration(Itemtype::Trust);
}

//接受扫描回调信号
void ScanWidget::doDissectionResult(QString sPath, double dProgress, int eType, QString sDetailInfo)
{
    // 确保处于正在扫描界面
    if (!m_isInScanningUI) {
        return;
    }

    // 不同的类型类型调用不同的接口
    if (m_antiViruswork->getVriusType() == EnginType::Rising) {
        if (RisingVirusType(eType) != RisingVirusType::RSmkTrusted) {
            //有异常的文件
            appendFileInfo(sPath, sDetailInfo);
            setScanErrorNum(++m_totalError);
        }
    } else {
        if (AHVirusType(eType) != AHVirusType::AHNormal) {
            //有异常的文件
            appendFileInfo(sPath, sDetailInfo);
            setScanErrorNum(++m_totalError);
        };
    }
    //扫描总数
    setScanNum(++m_totalScan);
    // 保存扫描路径和进度
    m_scanningFilePath = sPath;
    m_scanningProg = dProgress;
    //扫描路径
    setScanPath(sPath);
    setProgressValue(dProgress);
}

//单个文件的操作
void ScanWidget::operationFile(Itemtype type, QString sFilepath)
{
    switch (type) {
    case Itemtype::Repair:
        m_antiViruswork->requestRepairProblemFile(sFilepath);
        break;
    case Itemtype::Delete:
        break;
    case Itemtype::isolation:
        m_antiViruswork->requestChangeIsolationFile(true, sFilepath);
        break;
    case Itemtype::Trust:
        m_antiViruswork->requestChangeTrustFiles(true, sFilepath);
        break;
    }
}

// 判断可以操作的按钮状态  true 可以操作  false不可以操作
bool ScanWidget::checkOperationBtStatus()
{
    bool flag;
    //待操作项目
    int operation = 0;

    //总行数
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        //按钮的状态
        bool isChecked = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_CHECKED_STATUS).toBool();
        //是否被操作
        bool operaFlag = m_model->data(m_model->index(i, COLUMN_OPERATION), ROLE_OPERATION_FLAG).toBool();

        // 如果没有操作并且按钮是选中状态
        if ((!operaFlag) && isChecked) {
            ++operation;
        }
    }

    // 只要有一个待操作项 就是可以操作的
    if (operation != 0) {
        flag = true;
    } else {
        flag = false;
    }
    return flag;
}

// 一行的单独操作
void ScanWidget::singlRowOperation(QString filepath, Itemtype nType)
{
    //　点击的行号
    int nIndex = 0;
    //　ｍｘｚ　https://pms.uniontech.com/zentao/bug-view-43290.html
    //　由于以前输入参数是行号　但是排序以后行号会发生改变
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        QString fPath = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_VIRUSFILE_PATH).toString();
        //　对比带参路径和　表中的路径相比　从而或者真实的行号
        if (fPath == filepath) {
            nIndex = i;
            break;
        }
    }
    //路径
    QString filePath = m_model->data(m_model->index(nIndex, COLUMN_RISKS), ROLE_VIRUSFILE_PATH).toString();

    // 第一列
    m_model->setData(m_model->index(nIndex, COLUMN_RISKS), true, ROLE_CHECKED_STATUS);
    switch (nType) {
    case Itemtype::Repair:
        m_antiViruswork->requestRepairProblemFile(filePath);
        DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Repaired: %1").arg(1));
        break;
    case Itemtype::Delete:
        break;
    case Itemtype::isolation:
        m_antiViruswork->requestChangeIsolationFile(true, filePath);
        DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Quarantined: %1").arg(1));

        break;
    case Itemtype::Trust:
        m_antiViruswork->requestChangeTrustFiles(true, filePath);
        DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Trusted: %1").arg(1));
        break;
    }

    // 更新选择状态
    updateCheckAllStaus();

    m_model->setItem(nIndex, TABLE_COL_OPERATING, new QStandardItem(QString("true")));
    m_model->setData(m_model->index(nIndex, COLUMN_SUGGESTION), true, ROLE_OPERATING_FLAG);
    m_model->setData(m_model->index(nIndex, COLUMN_OPERATION), true, ROLE_OPERATION_FLAG);
    m_operationMap[nIndex] = true;

    // 最后路径经
    m_lastFileName = filePath;
    // 处理条数
    m_operationCount = 0;

    // 下拉框不可以操作 https://pms.uniontech.com/zentao/bug-view-46938.html
    m_combobox->setDisabled(true);
    m_exec->setDisabled(true);
}

// 创建日志的头文件标题
void ScanWidget::createLogTitle()
{
    QDir dir;
    //文件夹路径
    QString dir_path = QString("%1/.deepin-defender/natiav/").arg(QDir::homePath());
    if (!dir.exists(dir_path)) {
        dir.mkpath(dir_path);
    }
    QDateTime date = QDateTime::currentDateTime();
    QString time = date.toString("yyyyMMddhhmmss");
    //时间 .log 作为文件名
    m_logName = dir_path + time + ".log";
    QFile f(m_logName);
    if (!f.open(QIODevice::ReadOnly | QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "==Open ScanDate.log failed." << endl;
        return;
    }
}

// 当前行选中
void ScanWidget::currentRowClicked(QModelIndex index)
{
    // 当前点击的位置坐标
    int row = index.row();
    int column = index.column();
    QString operaFlag = m_model->index(row, TABLE_COL_OPERATION_FLAG).data(Qt::DisplayRole).toString();

    // 如果可以通过文字点击实现选中，　条件必须是　不在扫描中，当前行没有操作，并且操作栏不可以点击
    if ((column != TABLE_COL_OPEARTION) && (operaFlag == "false")) {
        // 为了避免操作 不可以在操作列点击
        // 按钮的状态
        bool isChecked = m_model->data(m_model->index(row, COLUMN_RISKS), ROLE_CHECKED_STATUS).toBool();
        // 改变按钮状态
        if (!isChecked) {
            m_model->setData(m_model->index(row, COLUMN_RISKS), true, ROLE_CHECKED_STATUS);
        } else {
            m_model->setData(m_model->index(row, COLUMN_RISKS), false, ROLE_CHECKED_STATUS);
        }
        // 判断全选的状态
        updateCheckAllStaus();
    } else {
        return;
    }
}

// 停止扫描
void ScanWidget::stopScan()
{
    // 设置扫描标题已经暂停
    m_t1->stop();
    // 停止进度设置定时器
    m_progSettingTimer->stop();
    // 不处于正在扫描界面
    m_isInScanningUI = false;

    if (EnginType::Ahprotector == m_antiViruswork->getVriusType()) {
        m_AhprotectorStopFlag = true;
    }
    // mxz https://pms.uniontech.com/zentao/bug-view-54737.html
    m_pbFinish->setEnabled(true);
    showFinishPage();
}

void ScanWidget::showFinishPage()
{
    //只有在加载完成以后才可以现实出结果
    // 结果页面有两种 分为没有异常和有异常
    if (m_totalError == 0) {
        // 如果异常数据是0
        if (m_currentType == 0) {
            //全盘扫描结束  没有异常
            m_titleLabel->setText(tr("Full scan finished, no threats found"));
            m_titleLabel->setToolTip(m_titleLabel->text());
        } else if (m_currentType == 1) {
            m_titleLabel->setText(tr("Quick scan finished, no threats found"));
            m_titleLabel->setToolTip(m_titleLabel->text());
        } else {
            m_titleLabel->setText(tr("Custom scan finished, no threats found"));
            m_titleLabel->setToolTip(m_titleLabel->text());
        }
        // 提示为空
        m_scanPath->setText(" ");
        m_scanPath->setToolTip("");
    } else {
        // 如果异常数据不为 0
        if (m_currentType == 0) {
            //全盘扫描结束   发现 X处异常
            m_titleLabel->setText(tr("Full scan finished, %1 threats found").arg(m_totalError));
            m_titleLabel->setToolTip(m_titleLabel->text());
        } else if (m_currentType == 1) {
            m_titleLabel->setText(tr("Quick scan finished, %1 threats found").arg(m_totalError));
            m_titleLabel->setToolTip(m_titleLabel->text());
        } else {
            m_titleLabel->setText(tr("Custom scan finished, %1 threats found").arg(m_totalError));
            m_titleLabel->setToolTip(m_titleLabel->text());
        }
        //提示 建议处理已发现的异常
        m_scanPath->setText(tr("Take actions to process the threats please"));
        m_scanPath->setToolTip(tr("Take actions to process the threats please"));
    }

    // 根据扫描出来的异常结果  判断展现第几页
    if (m_totalError == 0) {
        // 如果是没有异常 展现第一页 全选是没有勾选 并且不可以操作
        m_stackwidget->setCurrentIndex(PAGE_EMPTY);
        m_checkAll->setCheckState(Qt::CheckState::Unchecked);
        m_checkAll->setDisabled(true);

        //没有异常 结束按钮出现
        m_combobox->hide();
        m_exec->hide();
        // 状态按钮隐藏 完成按钮出现
        m_pbType->hide();
        m_pbDone->show();

    } else {
        // 如果是有异常 展现第二页 全选是勾选 并且可以操作
        m_stackwidget->setCurrentIndex(PAGE_TABLE);
        m_checkAll->setCheckState(Qt::CheckState::Checked);
        m_checkAll->setDisabled(false);

        m_combobox->show();
        m_exec->show();
        // 需要操作的过程中 状态按钮和完成隐藏
        m_pbType->hide();
        m_pbDone->hide();
    }

    for (int errorIndex = 0; errorIndex < m_totalError; errorIndex++) {
        m_model->setData(m_model->index(errorIndex, COLUMN_OPERATION), false, ROLE_OPERATION_FLAG);
    }

    //精度条隐藏
    m_progressBar->hide();

    //写入扫描数据
    writeScanDatalog();

    m_pbFinish->hide();
    m_pbRescan->show();
    m_pbRescan->setEnabled(false);

    // 安恒停止后会返回完成信号但是瑞星停止后不会返回，避免安恒点击停止添加两次安全日志
    if (!m_AhprotectorStopFlag) {
        // 添加安全日志
        if (0 == m_currentType) {
            DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Full scan, threats: %1").arg(m_totalError));
        } else if (1 == m_currentType) {
            DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Quick scan, threats: %1").arg(m_totalError));
        } else {
            DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("Custom scan, threats: %1").arg(m_totalError));
        }
    } else {
        m_AhprotectorStopFlag = false;
    }

//    QTimer::singleShot(1000, this, [=]() {
//        m_pbRescan->setEnabled(true);
//    });

    // 设置 界面扫描状态 为 结果展示中状态
    if (m_totalError == 0) {
        // 如果无异常结果，则直接设置引擎状态为free，将引擎扫描功能供给其他模块使用
        m_antiViruswork->setCurrentScanStatus(ScanStatus::Free);
    } else {
        // 设置状态是结果页面
        m_antiViruswork->setCurrentScanStatus(ScanStatus::ResultThreats);
    }
    // 更新返回按钮
    m_antiViruswork->updateBackButton();
    m_tableView->viewport()->repaint();

    m_pbRescan->setEnabled(true);
}

// 添加没有没有操作的异常项目
void ScanWidget::addThreats()
{
    // 1. 获得表中说有的数据
    int count = m_model->rowCount();
    // 没有操作的列表
    QString sPathlist;
    //操作了的列表
    QString rmPathlist;
    // 2. 判断表中是不是没有操作
    for (int i = 0; i < count; i++) {
        //是否被操作
        QString operaFlag = m_model->index(i, TABLE_COL_OPERATION_FLAG).data(Qt::DisplayRole).toString();
        if (operaFlag == "false") {
            QString filePath = m_model->index(i, TABLE_COL_INFO_PATH).data(Qt::DisplayRole).toString();
            // 没有处理的路径 进行拼接
            sPathlist = sPathlist + filePath + "[*]";
        } else {
            // 操作了的
            QString filePath = m_model->index(i, TABLE_COL_INFO_PATH).data(Qt::DisplayRole).toString();
            rmPathlist = rmPathlist + filePath + "[*]";
        }
    }
    // 如果有数据就发送添加信号
    if (!sPathlist.isEmpty()) {
        Q_EMIT onAddThreatsFile(sPathlist);
    }

    if (!rmPathlist.isEmpty()) {
        Q_EMIT readRemoveThreatsFile(rmPathlist);
    }
}

//　当前是否在操作中
bool ScanWidget::isCurrentOperating()
{
    bool flag = false;
    // 1. 获得表中说有的数据
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        QString operaFlag = m_model->index(i, TABLE_COL_OPERATING).data(Qt::DisplayRole).toString();
        // 是否在操作中
        if (operaFlag == "true") {
            flag = true;
            break;
        }
    }
    return flag;
}

// 处理异常中提示
void ScanWidget::showOperatingTip()
{
    DDialog *dialog = new DDialog(this);
    SET_ACC_NAME(dialog, operationTipDialog);
    dialog->setMinimumSize(QSize(DIALOG_WIDTH, DIALOG_HEIGHT));
    dialog->setMaximumSize(QSize(DIALOG_WIDTH, DIALOG_HEIGHT));
    dialog->setIcon(QIcon::fromTheme("dcc_login_tip"));
    //正在修复异常，请稍后，请稍候
    dialog->setMessage(tr("Removing threats, please wait..."));
    dialog->setWordWrapMessage(true);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->addButton(tr("OK", "button"));
    connect(dialog, SIGNAL(buttonClicked(int, const QString&)), this, SLOT(showOperatingTipHelp(int, const QString&)));

    dialog->exec();
}

void ScanWidget::showOperatingTipHelp(int index, const QString&)
{
    DDialog* dialog = qobject_cast<DDialog*>(sender());
    switch (index) {
    case 0:
        dialog->close();
        break;
    default:
        break;
    }
}

// 表头点击排序
void ScanWidget::sortByTableHeaderClicked(int index)
{
    if (index == TABLE_COL_OPEARTION) {
        //第三列不显示排序箭头
        m_tableView->horizontalHeader()->setSortIndicatorShown(false);
        return;
    }
    static bool bSortArc = true;

    Qt::SortOrder order = bSortArc ? Qt::AscendingOrder : Qt::DescendingOrder;
    m_tableView->horizontalHeader()->setSortIndicatorShown(true);
    m_tableView->horizontalHeader()->setSortIndicator(index, order);

    bSortArc = !bSortArc;

    // 根据不同的点击列  对应的列进行排序
    if (index == TABLE_COL_RISKS) {
        // 第二列排序
        m_tableView->sortByColumn(TABLE_COL_INFO_PATH);
    } else if (index == TABLE_COL_STATUS) {
        // 第三列排序
        m_tableView->sortByColumn(TABLE_COL_ACTION_STATUS);
    } else {
        return;
    }
}
